package com.cloudkinto.service.statistics.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cloudkinto.common.DicBusinessItemConstant;
import com.cloudkinto.common.common.DateUtils;
import com.cloudkinto.common.web.PageResult;
import com.cloudkinto.common.web.SingleResult;
import com.cloudkinto.dao.*;
import com.cloudkinto.entity.*;
import com.cloudkinto.extentity.stock.DeliveryCountDto;
import com.cloudkinto.extentity.stock.StockRecordStatisticDto;
import com.cloudkinto.service.statistics.StatisticsService;
import com.cloudkinto.service.statistics.vo.RecordPageRes;
import com.cloudkinto.service.statistics.vo.StatisticsRes;
import com.cloudkinto.service.stock.StockRecordService;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author zhangyy
 * @date 2020/6/19 9:26
 * @description:
 */
@Service
public class StatisticsServiceImpl implements StatisticsService {

    @Autowired
    private OrderInputDao orderInputDao;
    @Autowired
    private OrderOutputDao orderOutputDao;
    @Autowired
    private StockRecordDao stockRecordDao;
    @Autowired
    private ProductInfoDao productInfoDao;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private UserDao userDao;
    @Autowired
    private StockHistoryDao stockHistoryDao;
    @Autowired
    private StockRecordService stockRecordService;
    @Autowired
    private ShopDao shopDao;

    @Override
    public SingleResult statistics(Long userId, Long companyId) {
        StatisticsRes res = new StatisticsRes();

        UserDo userDo = userDao.selectById(userId);

        //昨日出货统计
        JSONObject yesterdayDelivery = yesterdayDelivery(userDo, companyId);
        res.setYesterdayDelivery(yesterdayDelivery);

        //今日入库数量
        JSONObject todayStock = todayStock(userDo, companyId);
        res.setTodayStock(todayStock);

        //在库总数量统计
        JSONObject stockTotalQuantity = stockTotalQuantity(userDo, companyId);
        res.setStockTotalQuantity(stockTotalQuantity);

        //昨日库存统计
        JSONObject yesterdayDeliveryFee = yesterdayDeliveryFee(userDo, companyId);
        res.setYesterdayDeliveryFee(yesterdayDeliveryFee);

        //前七日出货统计
        sevenDaysDeliveryList(userDo, companyId, res);

        //前7日库存费用统计
        sevenDaysStockFee(userDo, companyId, res);

        return SingleResult.success(res);
    }

    @Override
    public PageResult getListPage(Map<String, String> map) {
        IPage<OrderProductSellCountEntity> page = pageInit(map);
        List<OrderProductSellCountEntity> productSellCountEntities = orderOutputDao.selectBastSellProduct(page, map);
        PageResult result = new PageResult(productSellCountEntities, (int) page.getCurrent(), (int) page.getSize(), (int) page.getTotal(), (int) page.getPages());
        return result;
    }

    @Override
    public PageResult getgrownFastListPage(Map<String, String> map) {
        IPage<OrderProductSellCountEntity> page = pageInit(map);
        List<OrderProductSellCountEntity> productSellCountEntities = orderOutputDao.selecgrownFastProduct(page, map);
        PageResult result = new PageResult(productSellCountEntities, (int) page.getCurrent(), (int) page.getSize(), (int) page.getTotal(), (int) page.getPages());
        return result;
    }

    //查询分页列表之后对列表数据的处理
    private List<RecordPageRes> handlerListAfter(List<StockRecordDo> list) {
        List<RecordPageRes> result = new ArrayList<>();
        if (!CollectionUtils.isEmpty(list)) {
            list.forEach(stockRecordDo -> {
                RecordPageRes res = new RecordPageRes();
                res.setId(stockRecordDo.getProductInfoId());
                res.setCount(stockRecordDo.getCanSellCount());
                ShopDo shopDo = shopDao.selectById(stockRecordDo.getShopId());
                if (shopDo != null) {
                    res.setShopName(shopDo.getShopName());
                }
                ProductInfoDo productInfoDo = productInfoDao.selectById(stockRecordDo.getProductInfoId());
                if (productInfoDo != null) {
                    res.setCommoditySku(productInfoDo.getCommoditySku());
                }
                result.add(res);
            });
        }
        return result;
    }

    private QueryWrapper<StockRecordDo> queryBuild(Map<String, String> map) {
        QueryWrapper<StockRecordDo> wrapper = new QueryWrapper<>();
        if (StringUtils.isNotBlank(map.get("companyId"))) {
            wrapper.eq("company_id", map.get("companyId"));
        }
        wrapper.lt("can_sell_count", 50);
        wrapper.orderByDesc("id");
        return wrapper;
    }

    private IPage<OrderProductSellCountEntity> pageInit(Map<String, String> map) {
        IPage<OrderProductSellCountEntity> page = new Page();
        page.setSize(StringUtils.isNotBlank(map.get("pageSize")) ? Long.parseLong(map.get("pageSize")) : 10);
        page.setCurrent(StringUtils.isNotBlank(map.get("current")) ? Long.parseLong(map.get("current")) : 1);
        return page;
    }


    private JSONObject yesterdayDelivery(UserDo userDo, Long companyId) {
        JSONObject jsonObject = new JSONObject();

        Date date = DateUtils.passingDate(new Date(), -1);
        Date dateStart = DateUtils.getStartOfDay(date);
        Date dateEnd = DateUtils.getEndOfDay(date);

        LambdaQueryWrapper<OrderOutputDo> wrapper = new LambdaQueryWrapper<>();
        wrapper.ge(OrderOutputDo::getCreateTime, dateStart)
                .lt(OrderOutputDo::getCreateTime, dateEnd);
        if (companyId != null) {
            wrapper.eq(OrderOutputDo::getCompanyId, companyId);
        }
        if (userDo != null && userDo.getShopId() != null) {
            wrapper.eq(OrderOutputDo::getShopId, userDo.getShopId());
        }

        //昨日出货数量
        int count = orderOutputDao.selectCount(wrapper);
        jsonObject.put("count", count);
        wrapper = new LambdaQueryWrapper<>();
        wrapper.ge(OrderOutputDo::getUpdateTime, dateStart)
                .lt(OrderOutputDo::getUpdateTime, dateEnd);
        if (companyId != null) {
            wrapper.eq(OrderOutputDo::getCompanyId, companyId);
        }
        if (userDo != null && userDo.getShopId() != null) {
            wrapper.eq(OrderOutputDo::getShopId, userDo.getShopId());
        }
        wrapper.isNotNull(OrderOutputDo::getTrackNumber);
        //昨日实际出货数量

        wrapper.ge(OrderOutputDo::getStatus, DicBusinessItemConstant.outSendOut);
        int realCount = orderOutputDao.selectCount(wrapper);
        jsonObject.put("realCount", realCount);

        return jsonObject;
    }


    private JSONObject todayStock(UserDo userDo, Long companyId) {
        JSONObject jsonObject = new JSONObject();

        Date date = new Date();
        Date dateStart = DateUtils.getStartOfDay(date);
        Date dateEnd = DateUtils.getEndOfDay(date);

        LambdaQueryWrapper<OrderInputDo> wrapper = new LambdaQueryWrapper<>();
        wrapper.ge(OrderInputDo::getUpdateTime, dateStart)
                .lt(OrderInputDo::getUpdateTime, dateEnd)
                .eq(OrderInputDo::getStatus, DicBusinessItemConstant.putaway);
        ;
        if (companyId != null) {
            wrapper.eq(OrderInputDo::getCompanyId, companyId);
        }
        if (userDo != null && userDo.getShopId() != null) {
            wrapper.eq(OrderInputDo::getShopId, userDo.getShopId());
        }
        List<OrderInputDo> orderInputDoList = orderInputDao.selectList(wrapper);
        if (!CollectionUtils.isEmpty(orderInputDoList)) {
            jsonObject.put("count", orderInputDoList.size());
            double totalFee = 0;
            for (OrderInputDo orderInputDo : orderInputDoList) {
                totalFee += orderInputDo.getSeaFee();
                totalFee += orderInputDo.getClearanceFee();
                totalFee += orderInputDo.getServiceFee();
                totalFee += orderInputDo.getTaxFee();
            }
            jsonObject.put("fee", numberFormat(totalFee));
        } else {
            jsonObject.put("count", 0);
            jsonObject.put("fee", 0);
        }
        return jsonObject;
    }


    private JSONObject stockTotalQuantity(UserDo userDo, Long companyId) {
        JSONObject jsonObject = new JSONObject();
        Map<String, String> map = new HashMap<>();
        if (companyId != null) {
            map.put("companyId", companyId+"");
        }
        if (userDo.getShopId() != null) {
            map.put("shopId", userDo.getShopId()+"");
        }
        StockRecordStatisticDto res = stockRecordDao.getTotalCountFee(map);
        jsonObject.put("count", res.getCount());
        jsonObject.put("fee", res.getFee());
        return jsonObject;
    }


    private JSONObject yesterdayDeliveryFee(UserDo userDo, Long companyId) {
        JSONObject jsonObject = new JSONObject();

        Date date = DateUtils.passingDate(new Date(), -1);
        Date dateStart = DateUtils.getStartOfDay(date);
        Date dateEnd = DateUtils.getEndOfDay(date);

        LambdaQueryWrapper<StockHistoryDo> wrapper = new LambdaQueryWrapper<>();
        wrapper.ge(StockHistoryDo::getCreateDate, dateStart)
                .lt(StockHistoryDo::getCreateDate, dateEnd);

        if (companyId != null) {
            wrapper.eq(StockHistoryDo::getCompanyId, companyId);
        }
        if (userDo.getShopId() != null) {
            wrapper.eq(StockHistoryDo::getShopId, userDo.getShopId());
        }

        List<StockHistoryDo> stockHistoryDoList = stockHistoryDao.selectList(wrapper);
        if (!CollectionUtils.isEmpty(stockHistoryDoList)) {
            int count = 0;
            double fee = 0;
            for (StockHistoryDo stockHistoryDo : stockHistoryDoList) {
                count += (stockHistoryDo.getCanotSell() + stockHistoryDo.getCanSell());
                fee += stockHistoryDo.getCost();
            }
            jsonObject.put("count", count);
            jsonObject.put("fee", numberFormat(fee));
        } else {
            jsonObject.put("count", 0);
            jsonObject.put("fee", 0);
        }

        return jsonObject;
    }


    private List<JSONObject> sevenDaysDeliveryList(UserDo userDo, Long companyId, StatisticsRes res) {
        List<JSONObject> jsonObjectList = new ArrayList<>();
        Map<String, String> map = new HashMap<>();
        if (companyId != null) {
            map.put("companyId", companyId+"");
        }
        if (userDo.getShopId() != null) {
            map.put("shopId", userDo.getShopId()+"");
        }
        List<DeliveryCountDto> list = stockRecordDao.getDeliveryCount(map);

        res.setSevenDaysDeliveryTotalCount(list.stream().mapToInt(DeliveryCountDto::getRealCount).sum());
        res.setSevenDaysDeliveryList(list);
        return jsonObjectList;
    }


    private List<JSONObject> sevenDaysStockFee(UserDo userDo, Long companyId, StatisticsRes res) {
        List<JSONObject> jsonObjectList = new ArrayList<>();
        double totalFee = 0;
        for (int i = 1; i <= 7; i++) {
            JSONObject jsonObject = new JSONObject();

            Date date = DateUtils.passingDate(new Date(), -i);
            Date dateStart = DateUtils.getStartOfDay(date);
            Date dateEnd = DateUtils.getEndOfDay(date);

            LambdaQueryWrapper<StockHistoryDo> wrapper = new LambdaQueryWrapper<>();
            wrapper.ge(StockHistoryDo::getCreateDate, dateStart)
                    .lt(StockHistoryDo::getCreateDate, dateEnd);
            if (companyId != null) {
                wrapper.eq(StockHistoryDo::getCompanyId, companyId);
            }
            if (userDo.getShopId() != null) {
                wrapper.eq(StockHistoryDo::getShopId, userDo.getShopId());
            }

            List<StockHistoryDo> stockHistoryDoList = stockHistoryDao.selectList(wrapper);
            if (!CollectionUtils.isEmpty(stockHistoryDoList)) {
                double fee = 0;
                for (StockHistoryDo stockHistoryDo : stockHistoryDoList) {
                    fee += stockHistoryDo.getValue();
                }
                jsonObject.put("fee", numberFormat(fee));
                totalFee += fee;
            } else {
                jsonObject.put("fee", 0);
            }

            String format = new SimpleDateFormat("yyyy-MM-dd").format(date);
            jsonObject.put("date", format);
            jsonObjectList.add(jsonObject);
        }
        res.setSevenDaysStockTotalFee(numberFormat(totalFee));
        res.setSevenDaysStockFee(jsonObjectList);
        return jsonObjectList;
    }


    private double numberFormat(double f) {
        BigDecimal b = new BigDecimal(f);
        return b.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
    }


}